<?php
session_start(); // 开启session功能
/*
 * IntegrationTestingLite
 * 开源作品-PHP在线集成测试工具(单文件绿色版)
 * 程序特性：
 *      1. 单文件绿色版,部署超简单
 *      2. 支持多个数据库服务器切换
 * 使用方法：
 *      1. 复制本文件到web任意目录
 *      2. 修改$testconfig配置信息为实际内容
 *      3. 在浏览器输入链接路径,开始使用
 * 说明：写这个程序主要是为了辅助项目开发中的流程测试.如果您有兴趣一起完善这个小程序,欢迎使用git一起开发~感谢！
 * 项目周期：
 *      2017-10-23 立项开发
 *      2017-10-24 程序完成
 * 版权：不限商业用途! 如有修改代码请保留原著署名,并把修改后的代码回馈到作者邮箱：<14507247@qq.com>,促进本产品进步.做一个有公德心的正能量程序员~
 *      作者博客：http://www.cnblogs.com/sochishun/ 欢迎交流~
 * @version 1.0 <2017-10-23> SoChishun <14507247@qq.com> Added.
 * @version 1.1 <2017-10-27> SoChishun 新增倒计时自动刷新功能.
 * @version 1.2 <2017-11-2> SoChishun 改进计时器功能; 新增导出到Markdown文件功能.
 * @version 1.3 <2017-11-6 > SoChishun 新增host配置,并支持多个host下拉切换
 * @version 1.4 <2017-12-19> SoChishun 登录方法封装成JWTLite类,方便管理和迁移
 * @version 1.5 <2018-1-2> SoChishun 新增URL参数格式化工具
 * @version 1.6 <2018-1-12> SoChishun 引入ptshead.php头文件,简化代码,提高代码复用
 * @version 1.7 <2018-1-19> SoChishun URL参数格式化工具新增配置文件格式数据格式化功能
 */
// 版本号
define('VERSION', '1.7.0');
// 程序名称
define('APPNAME', 'IntegrationTestingLite');

// 引入头文件
include './pts_head.php';
// #JWTLite配置
// 页面访问验证配置
JWTLite::check_login();
list($loginid, $token, $loginexp) = array_values(JWTLite::$LOGIN_RESULT);

/**
 * 测试项目配置
 */
$testingConfig = array(
    /* 服务器-yourdomain */
    'yourdomain1' => array(
        'host' => ['127.0.0.1', 'www.yourdomain1.cn'], // 服务器,支持多个替换
        /* 项目 */
        'project' => array(
            'test_guessing' => array(
                'title' => '测试网综',
                'items' => array(
                    '观众登录' => '~/mapi/index.php?ctl=login&act=do_login&mobile=13950076987&verify_coder=9999',
                    '友盟推送' => '~/mapi/index.php?ctl=guessing&act=ymts&user_id=100515&video_id=1928',
                ),
                'replace_vars' => array('room_id' => 1926, 'video_id' => 1926, 'guessing_log_id' => 8, 'xiacai_id' => 7, 'guessing_id' => 14),
            ),
            'test_login' => array(
                'title' => '测试手机号密码登录',
                'items' => array(
                    '手机号+验证码登录(旧版登录并注册)' => '~/mapi/index.php?ctl=login&act=do_login&mobile=13950076987&verify_coder=9999',
                    '手机号+密码登录' => '~/mapi/index.php?ctl=login&act=login_by_loginid_with_password&mobile=13950076987&password=123456',
                    '手机号注册' => '~/mapi/index.php?ctl=login&act=regist_by_mobile_with_password&mobile=13950076987&password=123456&verify_coder=1234',
                    '忘记密码' => '~/mapi/index.php?ctl=user_center&act=update_password&mobile=13950076987&password=123456&verify_coder=1234',
                ),
            ),
        ),
    ),
    /* 服务器-local82 */
    'local82' => array(
        'host' => ['127.0.0.1:82'], // 服务器,支持多个替换
        /* 项目 */
        'project' => array(
            'test_admin_login' => array(
                'title' => '测试管理员注册和登录',
                'items' => array(
                    '管理员后台' => '~/index.php/liveadmin/login/index.html',
                    '用户名密码登录' => '~/index.php/liveapi/admin.login/login_by_loginid_with_password/loginid/admin/password/123456.html',
                    '发送短信验证码' => '~/index.php/liveapi/sms/send/mobile/13950076987/usefor/registration.html',
                    '手机验证码注册' => '~/index.php/liveapi/admin.registration/regist_by_mobile_with_smscode/mobile/13950076987/password/123/password_confirm/123/smscode/123.html',
                    '手机密码登录' => '~/index.php/liveapi/admin.login/login_by_mobile_with_password/mobile/13950076987/password/123456.html',
                    '手机验证码登录' => '~/index.php/liveapi/admin.login/login_by_mobile_with_sms/mobile/13950076987/sms_code/1234.html',
                ),
            ),
            'test_login' => array(
                'title' => '测试用户注册和登录',
                'items' => array(
                    '用户名密码注册' => '~/index.php/liveapi/registration/regist_by_loginid_with_password/loginid/sutroon/password/123456/password_confirm/123/captcha_code/1234.html',
                    '用户名密码登录' => '~/index.php/liveapi/login/login_by_loginid_with_password/loginid/sutroon/password/123456.html',
                ),
            ),
        ),
    ),
    'current_server' => 'yourdomain1', // 指定当前活动的服务器
);

// 浏览器参数
$httpHost = $_SERVER['HTTP_HOST']; // 当前服务器域名或ip
$curProjectId = input('project');
$curServId = input('server', $testingConfig['current_server']);
if (!$curServId || !array_key_exists($curServId, $testingConfig)) {
    exit('服务器ID [' . $curServId . '] 未配置');
}
$curTestConf = $testingConfig[$curServId]; // 当前测试配置数据
// 导出查询数据到Markdown文件
if (input('action') == 'exportmd') {
    header("Content-type:application/octet-stream");
    header("Content-Disposition:attachment; filename=itestlist-" . date('Ymd-His') . ".txt");
    if ($curProjectId && array_key_exists($curProjectId, $curTestConf['project'])) {
        $projects[] = $curTestConf['project'][$curProjectId];
    } else {
        $projects = $curTestConf['project'];
    }
    if ($projects) {
        $items = array();
        foreach ($projects as $project) {
            echo '### ', $project['title'], PHP_EOL, PHP_EOL;
            $items = $project['items'];
            foreach ($items as $text => $url) {
                echo $text, ' ', $url, PHP_EOL, PHP_EOL;
            }
        }
    } else {
        echo '没有查询到结果!';
    }
    echo PHP_EOL;
    exit();
}
?>
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title><?php echo APPNAME, ' - ', VERSION ?></title>
        <style type="text/css">
            body, td, th{font-size:13px; color:#333;}
            h1 a { color:#555; font-weight: normal;}
            fieldset { width:97%; margin-bottom: 10px;}
            iframe{width:100%;}
            a{ text-decoration: none;}
            .tb_url {width:60%;}
        </style>
    </head>
    <body>
        <script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
        <?php
        echo '<h1 title="', APPNAME, '-', VERSION, '">', APPNAME, ' ';
        echo '<a href="?token=', $token, '" title="新开一个页面" target="_blank" style="font-size:12px;">[新窗口]</a>';
        echo '<a href="?token=', $token, '" title="重置当前页面" style="font-size:12px;">[重置]</a>';
        echo '<a href="#" title="刷新当前页面" style="font-size:12px;" onclick="location.reload()">[刷新]</a>';
        echo '</h1>';
        // 用户登录信息
        if (isset($loginid)) {
            echo $loginid;
            echo ' [<a href="?action=logout" onclick="return confirm(\'您确定要注销登录吗?\');">注销登录</a>]';
        }
        echo ' 客户端IP:', $_SERVER['REMOTE_ADDR'], ' <span style="display:none">服务器IP:' . $httpHost . '</span> <a href="#" id="lnk-toggle-ipinfo">[...]</a>';
        $curProjects = isset($curTestConf['project']) ? $curTestConf['project'] : array(); // 当前服务器所有项目
        $curItems = array(); // 测试项目明细
        $curReplaceVarsStr = ''; // 可替换的url变量
        echo '<div style="margin:5px 0;">测试项目：<select id="slt-proj"><option value="">==选择项目==</option>';
        foreach ($curProjects as $projId => $projData) {
            echo '<option value="', $projId, '"', ($curProjectId == $projId ? ' selected="selected"' : ''), ' data-url="?server=', $curServId, '&project=', urlencode($projId), '&win_count=', input('win_count'), '&col_count=', input('col_count'), '&token=', $token, '">', (empty($projData['title']) ? $projId : $projData['title']), '</option>';
            if ($curProjectId == $projId) {
                $curItems = $projData['items'];
                if (isset($projData['replace_vars'])) {
                    $replaceVarsArr = $projData['replace_vars'];
                    foreach ($replaceVarsArr as $paraName => $paraVal) {
                        if ($curReplaceVarsStr) {
                            $curReplaceVarsStr .= "\n";
                        }
                        $curReplaceVarsStr .= "$paraName:$paraVal";
                    }
                }
            }
        }
        $winCountDef = empty($curItems) ? 0 : count($curItems);
        echo '</select>(', $winCountDef, '个接口) <a href="?server=', $curServId, '&project=', $curProjectId, '&action=exportmd&token=', $token, '" target="_blank" title="导出到MarkDown文件">[导出]</a></div>';
        $winCount = input('win_count');
        if (!$winCount) {
            $winCount = $winCountDef > 10 ? $winCountDef : 10;
        }
        $colCount = input('col_count', 2);
        if (!$colCount) {
            $colCount = 1;
        }
        // 窗口数量
        echo '<div style="float:left;">';
        echo '<fieldset style="width:240px;"><legend>基础设置<a href="#" class="lnk-switch">[-]</a></legend><div class="fieldset_content">';
        echo '<form>窗口数量：<input type="number" name="win_count" value="', $winCount, '" size="2" /><br />分栏数量：<input type="number" name="col_count" value="', $colCount, '" size="2" /><button type="submit">设置</button><input type="hidden" name="server" value="', $curServId, '" /><input type="hidden" name="project" value="', $curProjectId, '" /><input type="hidden" name="token" value="', $token, '" /></form>';
        echo '</div></fieldset>';
        echo '<fieldset style="width:240px;"><legend>主机替换<a href="#" class="lnk-switch">[-]</a></legend><div class="fieldset_content">';
        if (!empty($curTestConf['host'])) {
            $httpHost = current($curTestConf['host']);
        }
        echo '<input type="text" id="txt-host" value="', $httpHost, '" size="25" />';
        // 主机切换
        if (!empty($curTestConf['host'])) {
            echo '<div style="margin:3px 0"><select id="slt-host"><option value="">==切换主机==</option>';
            foreach ($curTestConf['host'] as $host) {
                echo '<option value="', $host, '">', $host, '</option>';
            }
            echo '</select></div>';
        }
        echo '<button id="btn-replace-host">替换</button></div></fieldset>';
        echo '</div>';
        // 变量替换
        $placeholder = "每个变量一行,例如:\nvar1:val1\nvar2:val2";
        echo '<div style="float:left;"><fieldset style="width:650px;"><legend>URL变量批量替换<a href="#" class="lnk-switch">[-]</a></legend><div class="fieldset_content"><textarea id="tb-replace-vars" cols="90" rows="', (empty($curTestConf['host']) ? 7 : 10), '" placeholder="', $placeholder, '">', $curReplaceVarsStr, '</textarea><br /><button type="button" id="btn-replace">替换</button></div></fieldset></div>';
        // 变量格式化
        echo '<div style="float:left;"><fieldset style="width:650px;"><legend>URL参数格式化工具<a href="#" class="lnk-switch">[-]</a></legend><div class="fieldset_content"><textarea id="tb-urlparam-orgin" cols="90" rows="6" placeholder="URL参数,PHP数组格式或者JSON格式或者配置文件"></textarea><br />源格式：<input type="radio" name="urlparamformattype" value="phparray" />PHP数组<input type="radio" name="urlparamformattype" value="json" checked="checked" />JSON<input type="radio" name="urlparamformattype" value="ini" />配置文件 <button type="button" id="btn-format-urlparam" style="margin-bottom:2px">格式化</button><br /><textarea id="tb-urlparam-format-result" cols="90" rows="3" placeholder="格式化结果"></textarea></div></fieldset></div>';

        echo '<div style="clear:left"></div>';
        $adv_urls = array(
            'aTool在线HTTP接口测试' => 'http://www.atool.org/httptest.php',
            'Getman在线HTTP接口测试' => 'https://getman.cn/',
            'ouapi在线HTTP接口测试' => 'http://www.ouapi.com/',
        );
        if ($adv_urls) {
            echo '<fieldset><legend>更多在线HTTP接口测试工具<a href="#" class="lnk-switch">[-]</a></legend><div class="fieldset_content">';
            foreach ($adv_urls as $title => $url) {
                echo '<a href="', $url, '" target="_blank">[', $title, ']</a> ';
            }
            echo '</div></fieldset>';
        }
        echo '<div style="color:#999;margin-bottom:10px;font-size:11px;">友情提示：<span style="color:#F00;">打开浏览器的调试窗口,可以达到事半功倍的效果哦!</span></div>';
        $i = 1;
        $colStyle = $colCount > 1 ? ' style="float:left; width:' . floor(100 / $colCount) . '%"' : '';
        if ($winCountDef > 0) {
            foreach ($curItems as $title => $url) {
                if ($url) {
                    if ($url[0] == '~') {
                        $url = 'http://' . $httpHost . substr($url, 1);
                    }
                } else {
                    $url = 'http://' . $httpHost;
                }
                buildWindow($i, $colStyle, $title, $url);
                $i++;
            }
        }
        while ($i <= $winCount) {
            buildWindow($i, $colStyle, '', 'http://' . $httpHost);
            $i++;
        }
        echo '<div style="clear:left"></div>';
        ?>

        <script type="text/javascript">
            // 2018-1-15
            console.log("%c" + $('h1').attr('title') + "\nEmail:14507247@qq.com" + "\nProject:https://gitee.com/sochishun/ptoolsuite\nTip: <?php echo "今天是", date('Y年m月d日'), ' 星期', mb_substr('天一二三四五六', date('w'), 1), ' 第', intval(date('W')), date('周 一年中第z天') ?>\n\n欢迎使用 :)", 'color:#090;');
            // 2017-11-7 主机快捷切换
            $('#slt-host').change(function () {
                var val = $(this).val();
                if (val) {
                    $('#txt-host').val(val);
                }
            })
            // 2017-10-28 服务器信息改为显隐控制，提高安全性，防止被窥探
            $('#lnk-toggle-ipinfo').click(function () {
                var $a = $(this);
                if ($a.text() == '[...]') {
                    $a.text('[x]').prev().show();
                } else {
                    $a.text('[...]').prev().hide();
                }
                return false;
            })
            $('#slt-proj').change(function () {
                var $slt = $(this);
                if (!$slt.val()) {
                    return;
                }
                var url = $slt.find('option[value="' + $slt.val() + '"]').data('url');
                location.href = url;
            })
            $('input[name="count"]').blur(function () {
                if ($(this).val() == '') {
                    $(this).val(10);
                }
            })
            // 展开或收起fieldset内容
            $('legend .lnk-switch').click(function () {
                var 　 $a = $(this);
                if ($a.text() == '[-]') {
                    $a.text('[+]').attr('title', '展开');
                    $a.parent().parent().find('.fieldset_content').hide();
                } else {
                    $a.text('[-]').attr('title', '收起');
                    $a.parent().parent().find('.fieldset_content').show();
                }
            })
            $('.btn_open').click(function () {
                var $fieldset = $(this).parent();
                var url = $fieldset.find('.tb_url').val();
                var $ifrm = $fieldset.find('iframe');
                if (url.length < 1) {
                    return;
                }
                var isIframeType = true;
                if (isIframeType) {
                    $ifrm.attr('src', url);
                    return;
                }
                // 2017-11-7 see: https://stackoverflow.com/questions/17694807/how-to-set-custom-http-headers-when-changing-iframe-src
                $.ajax({
                    type: "GET",
                    url: url,
                    contentType: "application/json",
                    beforeSend: function (xhr, settings) {
                        xhr.setRequestHeader("some_custom_header", "foo");
                    },
                    success: function (data) {
                        $ifrm.attr('src', "about:_blank")
                        $ifrm.contents().find('html').html(data);
                    }
                });
            })
            $('.btn_open_in_new_window').click(function () {
                var $fieldset = $(this).parent();
                var $input = $fieldset.find('.tb_url');
                if ($input.val().length < 1) {
                    return;
                }
                window.open($input.val());
            })
            /**
             * 替换url中的变量
             * @param string url
             * @param string arg
             * @param string val
             * @param boolean append 如果变量不存在是否追加
             * @returns {@var;url|String|@var;replaceText}
             * @since 2017-10-23
             * @see http://www.cnblogs.com/doseoer/p/5747715.html
             */
            function replace_url_param(url, arg, val, append) {
                var pattern = arg + '=([^&]*)';
                var replaceText = arg + '=' + val;
                if (url.match(pattern)) {
                    url = url.replace(eval('/(' + arg + '=)([^&]*)/gi'), replaceText)
                } else {
                    if (append) {
                        url = url + (url.match('[\?]') ? '&' : '?') + replaceText;
                    }
                }
                return url;
                //return url.match(pattern) ? url.replace(eval('/(' + arg + '=)([^&]*)/gi'), replaceText) : (url.match('[\?]') ? url + '&' + replaceText : url + '?                    ' + replaceText);
            }
// 批量替换url主机信息 2017-10-25
            $('#btn-replace-host').click(function () {
                var txt = $('#txt-host').val();
                if (!txt) {
                    return;
                }
                var $location, url;
                $('.tb_url').each(function () {
                    $location = $(this);
                    url = $location.val();
                    if (url) {
                        url = url.replace(/(http[s]?:\/\/)([^\/]*)/, "$1" + txt);
                        $location.val(url);
                    }
                });
            })
// 批量替换url变量
            $('#btn-replace').click(function () {
                var txt = $('#tb-replace-vars').val();
                if (txt.indexOf(':') < 0) {
                    return;
                }
                var $location, url;
                var txtarr = txt.split("\n");
                var txtitemarr;
                $('.tb_url').each(function () {
                    $location = $(this);
                    url = $location.val();
                    if (url) {
                        for (var i in txtarr) {
                            txtitemarr = txtarr[i].split(':', 2);
                            url = replace_url_param(url, txtitemarr[0], txtitemarr[1]);
                        }
                        $location.val(url);
                    }
                });
            });

            // 格式化url变量 2018-1-2
            $('#btn-format-urlparam').click(function () {
                var paramstr = $('#tb-urlparam-orgin').val();
                var fmtstr = $('input[name="urlparamformattype"]:checked').val();
                if (!paramstr) {
                    return false;
                }
                if (!fmtstr) {
                    alert('源格式未选择!');
                    return false;
                }
                var content = '';
                switch (fmtstr) {
                    case 'phparray':
                        content = paramstr.replace(/=>/g, '=').replace(/'/g, '').replace(/\s/g, '').replace(/,/g, '&');
                        break;
                    case 'json':
                        content = paramstr.replace(/:/g, '=').replace(/['|"]/g, '').replace(/\s/g, '').replace(/,/g, '&');
                        break;
                    case 'ini':
                        content = paramstr.replace(/ = /g, '=').replace(/['|"]/g, '').replace(/\s/g, '').replace(/;/g, '&');
                        break;
                }
                $('#tb-urlparam-format-result').val(content);
                return false;
            });
// 定时刷新 2017-10-27
            $('.timer input').blur(function () {
                var $input = $(this);
                var time = $input.val();
                if (!time || (time && time < 0)) {
                    $input.val(0);
                    return;
                }
                var interval = $input.data('interval');
                if (interval) {
                    clearInterval(interval);
                }
                if (time == 0) {
                    var $span = $input.parent().find('span');
                    $span.text('                    0/');
                    $span.data('n', 0);
                    return;
                }
                interval = setInterval(countDown_(this), 1000);
                $input.data('interval', interval);
            })
// 解决setInterval无法传参
            function countDown_(input) {
                return function () {
                    countDown(input);
                }
            }
            function countDown(input) {
                var $input = $(input);
                var second = $input.val();
                if (second < 1) { // 如果中途输入0会自动停止
                    var interval = $input.data('interval');
                    if (interval) {
                        clearInterval(interval);
                    }
                    return;
                }
                var $span = $input.parent().find('span');
                var n = $span.data('n');
                if (!n) {
                    n = 0;
                }
                n++;
                if (n > second) {
                    var $fieldset = $span.parent().parent();
                    $fieldset.find('iframe').attr('src', "_blank");
                    $fieldset.find('iframe').attr('src', $fieldset.find('.tb_url').val());
                    n = 1;
                }
                $span.data('n', n);
                $span.text(n + '/')
            }
        </script>
    </body>
</html>
<?php

/**
 * 生成子窗体
 * @param type $i 编号
 * @param type $colStyle 分栏样式
 * @param type $title 标题
 * @param type $url 网址
 * @version 2017-10-27
 */
function buildWindow($i, $colStyle, $title, $url) {
    echo '<div', $colStyle, '><fieldset><legend>', $i, '.<a href="#" class="lnk-switch" title="展开或收起当前区块的内容">[-]</a><input placeholder="名称" value="', $title, '" size="60" /></legend><div style="display:none">请求方式：<input type="radio" name="result_type', $i, '" value="ajax" />AJAX<input type="radio" name="result_type', $i, '" value="iframe" checked="checked" />IFrame</div><input type="text" class="tb_url" placeholder="http://" value="', $url, '" /><button class="btn_open">打开</button><button class="btn_open_in_new_window">新窗口打开</button> <span class="timer">定时刷新<span>0/</span><input type="number" step="5" value="0" style="width:60px;" title="0表示停止计时器,输入正整数并点击页面任意空白处即可启动定时器" /><a href="###"title="定时器使用说明' . PHP_EOL . '1. 鼠标移开输入框,并点击任意页面空白处即可启动定时器.' . PHP_EOL . '2. 建议设置值不少于10秒,防止整个页面卡死.' . PHP_EOL . '3. 设置值为0,则自动停止定时器.">(?)</a></span>';
    echo '<div class="fieldset_content"><iframe src="about:_blank" height="230"></iframe></div>';
    echo '</fieldset></div>';
}
